package uaiContacts.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import uaiContacts.model.Grupo;
import uaiContacts.repository.GrupoRepository;
import uaiContacts.vo.GrupoListVO;

@Service
@Transactional
public class GrupoService {

	@Autowired
	private GrupoRepository grupoRepository;
	
	@Transactional(readOnly = true)
    public GrupoListVO findAll(int page, int maxResults) {
        Page<Grupo> result = executeQueryFindAll(page, maxResults);

        if(shouldExecuteSameQueryInLastPage(page, result)){
            int lastPage = result.getTotalPages() - 1;
            result = executeQueryFindAll(lastPage, maxResults);
        }

        return buildResult(result);
    }

    public void save(Grupo grupo) {
        grupoRepository.save(grupo);
    }

    @Secured("ROLE_ADMIN")
    public void delete(int grupoId) {
    	grupoRepository.delete(grupoId);
    }

    @Transactional(readOnly = true)
    public GrupoListVO findByNomeLike(int page, int maxResults, String nome) {
        Page<Grupo> result = executeQueryFindByNome(page, maxResults, nome);

        if(shouldExecuteSameQueryInLastPage(page, result)){
            int lastPage = result.getTotalPages() - 1;
            result = executeQueryFindByNome(lastPage, maxResults, nome);
        }

        return buildResult(result);
    }

    private boolean shouldExecuteSameQueryInLastPage(int page, Page<Grupo> result) {
        return isUserAfterOrOnLastPage(page, result) && hasDataInDataBase(result);
    }

    private Page<Grupo> executeQueryFindAll(int page, int maxResults) {
        final PageRequest pageRequest = new PageRequest(page, maxResults, sortByNomeASC());

        return grupoRepository.findAll(pageRequest);
    }

    private Sort sortByNomeASC() {
        return new Sort(Sort.Direction.ASC, "nome");
    }

    private GrupoListVO buildResult(Page<Grupo> result) {
        return new GrupoListVO(result.getTotalPages(), result.getTotalElements(), result.getContent());
    }

    private Page<Grupo> executeQueryFindByNome(int page, int maxResults, String nome) {
        final PageRequest pageRequest = new PageRequest(page, maxResults, sortByNomeASC());

        return grupoRepository.findByNomeLike(pageRequest, "%" + nome + "%");
    }

    private boolean isUserAfterOrOnLastPage(int page, Page<Grupo> result) {
        return page >= result.getTotalPages() - 1;
    }

    private boolean hasDataInDataBase(Page<Grupo> result) {
        return result.getTotalElements() > 0;
    }
}
